﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Musicman.Client2.Components;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;

namespace Musicman.Client2
{
    public partial class CopyForm : Form
    {
        public FileDownloader FileDownloader { get; private set; }
        private Dictionary<object, ProgressLabel> progressInfos;
        private Queue<ProgressLabel> progressLabelPool;
        private object locker = new object();
        
        // drawing variables
        private Rectangle leftPaneRect;
        private Rectangle rightPaneRect;
        private Rectangle paneArc;
        private Rectangle centralPane;

        private float wmu = 0f;
        private float hmu = 0f;
        private Color SINGLE_GRADIENT_COLOR1 = Color.Orange;
        private Color SINGLE_GRADIENT_COLOR2 = Color.WhiteSmoke;
        private Color OVERALL_GRADIENT_COLOR1 = Color.Orange;
        private Color OVERALL_GRADIENT_COLOR2 = Color.Red;

        #region Form Dragging API Support
        //The SendMessage function sends a message to a window or windows.

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]

        static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

        //ReleaseCapture releases a mouse capture

        [DllImportAttribute("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]

        public static extern bool ReleaseCapture();

        private void CopyForm_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                ReleaseCapture();
                SendMessage(this.Handle, 0xa1, 0x2, 0);
            }
        }

        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (keyData == Keys.Escape)
            {
                this.Hide();
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }
        #endregion

        public CopyForm()
        {
            InitializeComponent();
            this.Visible = false;
            this.DoubleBuffered = true;
            this.KeyPreview = true;

            progressInfos = new Dictionary<object, ProgressLabel>();
            progressLabelPool = new Queue<ProgressLabel>(5);

            this.FileDownloader = new FileDownloader();
            this.FileDownloader.DownloadProgressChanged += new ProgressChangedEventHandler(FileDownloader_DownloadProgressChanged);
            this.FileDownloader.DownloadCompleted += new AsyncCompletedEventHandler(FileDownloader_DownloadCompleted);
            this.FileDownloader.FileCountChanged += new EventHandler(FileDownloader_DownloadingStarted);
            for (int i = 0; i < 5; i++)
            {
                ProgressLabel pl = CreateProgressLabel();
                progressLabelPool.Enqueue(pl);
                pnlProgressBars.Controls.Add(pl);
            }

            // drawing variables
            wmu = (float)this.Width / 8f;
            hmu = (float)(this.Height - 60) / 8f;
            paneArc = new Rectangle(10, (int)(hmu / 2f), (int)(3f * wmu), (int)(hmu));
            leftPaneRect = new Rectangle(10, (int)hmu, (int)(3f * wmu), (int)(6f * hmu));
            rightPaneRect = new Rectangle((int)(5f * wmu) - 20, (int)hmu, (int)(3f * wmu), (int)(6f * hmu));
            centralPane = new Rectangle((int)(3f * wmu) + 10, 0, (int)(2f * wmu) - 30, (int)(2 * hmu));

        }

        private ProgressLabel CreateProgressLabel()
        {
            ProgressLabel res = new ProgressLabel();
            res.TextAlign = ContentAlignment.MiddleCenter;
            res.ForeColor = Color.Black;
            return res;
        }

        private ProgressLabel GetProgressInfo()
        {
            ProgressLabel res = null;
            if (progressLabelPool.Count != 0)
            {
                res = progressLabelPool.Dequeue();
            }
            else
            {
                res = CreateProgressLabel();
                pnlProgressBars.Controls.Add(res);
            }
            res.Visible = true;
            res.Size = new Size(pnlProgressBars.Width - 20, 20);
            return res;
        }

        private void CopyForm_Load(object sender, EventArgs e)
        {
            System.Drawing.Drawing2D.GraphicsPath myPath = new System.Drawing.Drawing2D.GraphicsPath();
            myPath.AddRectangle(leftPaneRect);
            myPath.AddRectangle(rightPaneRect);
            myPath.AddArc(paneArc, 180f, 180f);
            paneArc.Y = (int)(6.5f * hmu) - 1;
            myPath.AddArc(paneArc, 0f, 180f);
            paneArc.X = (int)(5f * wmu) - 20;
            myPath.AddArc(paneArc, 0f, 180f);
            paneArc.Y = (int)((int)(hmu / 2f));
            myPath.AddArc(paneArc, 180f, 180f);

            myPath.AddArc(centralPane, 180f, 180f);
            Region myRegion = new Region(myPath);
            this.Region = myRegion;
        }


        void FileDownloader_DownloadingStarted(object sender, EventArgs e)
        {
            if (this.dgvQueuedFiles.InvokeRequired)
            {
                EventHandler eh = new EventHandler(FileDownloader_DownloadingStarted);
                this.Invoke(eh, new object[] { sender, e });
            }
            else
            {
                this.lblFilesLeft.Text = String.Format("Files count: {0}", FileDownloader.FilesCount);
                DownloadFileArgs[] args = sender as DownloadFileArgs[];
                dgvQueuedFiles.Rows.Clear();
                foreach (DownloadFileArgs arg in args)
                {
                    dgvQueuedFiles.Rows.Add(arg.UserSuppliedState, arg.SearchFile.Name);
                }
                this.dgvQueuedFiles.Refresh();
            }
        }

        void FileDownloader_DownloadCompleted(object sender, AsyncCompletedEventArgs e)
        {
            if (this.InvokeRequired)
            {
                AsyncCompletedEventHandler aceh = new AsyncCompletedEventHandler(FileDownloader_DownloadCompleted);
                this.Invoke(aceh, new object[] { sender, e });
            }
            else
            {
                lock (locker)
                {
                    if (progressInfos.ContainsKey(e.UserState))
                    {
                        progressInfos[e.UserState].Visible = false;
                        progressLabelPool.Enqueue(progressInfos[e.UserState]);
                        progressInfos.Remove(e.UserState);
                    }
                    int i = 0;
                    foreach (object o in progressInfos.Keys)
                    {
                        progressInfos[o].Location = new Point(10, i * 25 + 5);
                        i++;
                    }
                    if (progressInfos.Count == 0)
                    {
                        lblOveralProgress.Percentage = 0;
                    }
                }
            }            
        }

        void FileDownloader_DownloadProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (this.InvokeRequired)
            {
                ProgressChangedEventHandler pceh = new ProgressChangedEventHandler(FileDownloader_DownloadProgressChanged);
                this.Invoke(pceh, new object[] { sender, e });
            }
            else
            {
                DownloadProgressChangedEventArgs args = e as DownloadProgressChangedEventArgs;
                lock (locker)
                {
                    ProgressLabel pl = null;
                    if (!progressInfos.ContainsKey(args.UserState))
                    {
                        pl = GetProgressInfo();
                        pl.Visible = true;
                        pl.Location = new Point(10, progressInfos.Count * 25 + 5);
                        progressInfos[args.UserState] = pl;
                    }
                    else
                    {
                        pl = progressInfos[args.UserState];
                    }
                    pl.Percentage = args.ProgressPercentage;
                    pl.Text = String.Format("{0} %", args.ProgressPercentage);
                    lblOveralProgress.Percentage = args.OverallPercentage;
                }
            }
        }

        private void CopyForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (e.CloseReason == CloseReason.UserClosing)
            {
                e.Cancel = true;
                this.Hide();
            }
            else
            {
                this.FileDownloader.CancelAll();
            }
        }


        private void btnLBackground_Click(object sender, EventArgs e)
        {
            this.Visible = false;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.FileDownloader.CancelAll();
        }
    }
}
